不讲武德的软件们
咱们国家的人最喜欢自己给自己创造困难,就比如墙这个东西,普通人可能感觉不太大,但对于开发者来说问题就大了。这几十年来诞生了不知道多少工具来解决各种围绕墙的难题,而几乎所有奇思妙想、奇技淫巧都是国内首创的(在这方面咱们国人可谓领先世界)。为啥?因为有需求才有市场,国外人家根本不会遇到这种难题,当然就不需要解决这些难题的工具了。
比如开发中一个很常见的场景,使用 Docker 拉镜像的时候,就需要出墙。从 docker.io 上拉镜像还好,虽然 Dockerhub 主域名被墙了,但 docker.io 这个存储镜像的域名却逃过一劫,就是在某些情况下速度极慢。不过倒是可以用国内镜像站解决大部分问题。但倘若要从 ghcr.io、谷歌云等地方拉镜像就不行了,这些域名和 IP 都被墙的死死的。这时候就不得不配置代理了。
Linux 下常见的代理配置方式是开个 Clash 之类的代理软件,然后export ALL_PROXY/HTTP_PROXY/HTTPS_PROXY
设置环境变量,这样配置之后大多数「识相」的软件就会自动使用设置的代理地址。坏就坏在少数极端反 RFC 软件分子「不讲武德」,比如 Docker,比如 apt,比如 git,根本不理会这些环境变量,就是走直连。要给这些软件设置代理就费事了。
Docker 这样还情有可原,毕竟人家是 C/S 架构,你命令行操作的只是 docker-cli,人家 docker daemon 也没必要关照你的环境变量。因此咱们可以用 Docker 守护进程的配置文件来设置代理(来源):
|
|
而 apt 身为一个在终端运行的命令行工具,配置代理居然也要在配置文件中加这一行让人摸不着头脑的配置(来源):
|
|
git 则又有自己的配置文件。
一百种软件一百个样,为每个软件都在自己的配置文件中配置代理,可得累坏开发者了!
对于 apt 和各种包管理器(npm、go、pip 等)来说,自己用用倒还可以使用国内镜像,例如 tuna 镜像站等。但在 Docker build 镜像的时候,你总不能把的镜像地址和127.0.0.1:7890
在 Dockerfile 里四处乱写吧?那样老外用你的镜像的时候,一运行 npm install 就得连到中国下软件,然后再报个 7890 端口无法连接的错误,岂不让人贻笑大方?实在太不国际化了。
半吊子的解决方案
之前偶然间发现了一个命令行工具gg,可以在一定程度解决代理问题。它用的是一种类似隧道的解决方案,可以在配置好代理节点后,强制在 shell 中运行的命令走代理,比如这样:
|
|
或者直接打开一个全局强制代理的 shell:
|
|
但缺点也很明显,就是支持终端程序,像 Docker 这样的 C/S 架构的就不行了,Docker build 就更不行了。
dae:eBPF 网卡级代理
要解决这些问题,基本上只能用 tproxy 了。但我嫌 iptables 规则配置起来太麻烦,于是在网上搜有没有更简单的(配置更少的)方案,还真让我给找到了。
dae是一个用 Go 语言开发,基于 eBPF 实现的网卡级代理工具。而且不止代理本机,还能作为网关转发流量,让局域网内的设备也能科学上网。它能完美解决如上所述所有需求,堪称杀手级软件。
配置 dae
dae 支持多种代理协议,不仅限于 http 和 socks5,还支持常见的 trojan、vless 等。由于我还是习惯使用 Clash 管理代理规则,因此在安装之后,直接写了个最简配置,把除了 Clash 自己之外的流量都路由到 7890 端口上:
|
|
这里做一下简单解释。
WAN & LAN
|
|
WAN 是为本机绑定的网卡,填入 VPS 自身的网卡。我这台是 ESXI 的虚拟机,因此是 ens160,云服务器一般是 eth0,可以ip a
自己看一下。LAN 是为局域网转发的网卡,这里因为需要为 Docker 管理的容器转发代理流量,因此就填 docker0,这个是固定的。
注意 Docker build 的时候其实也是开了一个容器在里面隔离构建,所以上游接到的也是 docker0 的虚拟网卡。
关于本机网卡和 Docker 网卡,可以看一下这篇解释:https://stackoverflow.com/questions/37536687/what-is-the-relation-between-docker0-and-eth0
pname
|
|
指定了走直连的进程,这里显然是直接让 Clash 本身走直连,避免回环。只需要在括号内填写进程名即可,不需要加完整路径。可以使用如下命令来看:
|
|
可以根据官方文档的例子对配置文件进行优化,比如加入更多在 dae 层就可以完成的分流动作,而不必转发到 Clash 层,这样可以提高一点速度。比如这里给出一个更复杂一点的配置文件:
|
|
配置 ufw
如果使用 ufw 作为防火墙的话,还有个坑,就是需要放行 tproxy 的 12345 端口和 mark 为 0x8000000 的转发流量。因为不知道这一点,我还专门去提了个issue。十分感谢热心开发者的解答~
先使用 ufw allow 放行 12345 端口(如果你的 ufw 是默认放行的话,就不需要了):
|
|
然后编辑/etc/ufw/before.rules
,找找看在大概这两行注释之间加入如下配置:
|
|
还有一个 ipv6 的,/etc/ufw/before6.rules
:
|
|
然后输入ufw disable && ufw enable
重启下 ufw 即可。必要时还需要重启下 dae:service dae restart
。
测试访问
|
|
既可以在本机上直接使用,又可以在容器中连上。这样就算成功了。